//定义食物类
class Food {
    constructor() {
        // 获取页面中的food元素并将其赋值给element
        this.element = document.getElementById('food');
    }
    get x() {
        return this.element.offsetLeft;
    }
    get y() {
        return this.element.offsetTop;
    }
    // 修改食物的位置
    change() {
        /*
            需求：
            1.随机生成的位置
            2.位置的范围在0-290之间
            3.因为蛇每移动一步是10像素，所以要求食物所在的位置必须被10整除
        */
        let left = Math.round(Math.random() * 29) * 10;
        let top = Math.round(Math.random() * 29) * 10;
        this.element.style.left = left + 'px';
        this.element.style.top = top + 'px';
    }
}
//定义积分类
class ScorePanel {
    /**
     * @param maxLevel 如果不传，最大值默认就是10
     * @param upScore 吃到一个食物加多少分？
     */
    constructor(maxLevel = 10, upScore = 1) {
        this.score = 0; //计分
        this.level = 1; //等级
        this.scoreEle = document.getElementById('score');
        this.levelEle = document.getElementById('level');
        this.maxLevel = maxLevel;
        this.upScore = upScore;
    }
    // 设置一个加分的方法
    addScore() {
        // 让分数增加   每10分升一级
        this.scoreEle.innerHTML = String(++this.score);
        if (this.score % this.upScore === 0) {
            this.levelUP();
        }
    }
    levelUP() {
        if (this.level < this.maxLevel) {
            this.levelEle.innerHTML = String(++this.level);
        }
    }
}
// 定义蛇类
class Snake {
    constructor() {
        this.element = document.getElementById('snake');
        this.head = document.querySelector('#snake>div'); //取第一个div
        this.bodies = this.element.getElementsByTagName('div');
    }
    // 获取蛇的坐标
    get Y() {
        return this.head.offsetTop;
    }
    get X() {
        return this.head.offsetLeft;
    }
    // 设置蛇头的坐标
    set X(value) {
        // 如果新值和旧值相同，则直接返回不再修改
        if (this.X === value) {
            return;
        }
        // X的值合法范围0-290之间
        if (value < 0 || value > 290) {
            //进入判断，蛇撞墙了
            throw new Error("撞墙了，游戏结束，GameOver！");
        }
        // 修改x时，是在修改水平坐标，蛇在左右移动，蛇在向左移动，不能向右掉头
        if (this.bodies[1] && this.bodies[1].offsetLeft === value) {
            console.log('发生了掉头');
            if (value > this.X) {
                // 如果新值value大于旧值x，则说明蛇在向右走，此时发生掉头，应该使蛇继续向左走
                value = this.X - 10;
            }
            else {
                // 向左走
                value = this.X + 10;
            }
        }
        // 移动身体
        this.moveBody();
        this.head.style.left = value + 'px';
        // 检查有没有撞到自己
        this.checkHeadBody();
    }
    set Y(value) {
        // 如果新值和旧值相同，则直接返回不再修改
        if (this.Y === value) {
            return;
        }
        // Y的值合法范围0-290之间
        if (value < 0 || value > 290) {
            //进入判断，蛇撞墙了
            throw new Error("撞墙了，游戏结束，GameOver！");
        }
        // 修改y时，是在修改水平坐标，蛇在左右移动，蛇在向左移动，不能向右掉头
        if (this.bodies[1] && this.bodies[1].offsetTop === value) {
            // console.log('发生了掉头');
            if (value > this.Y) {
                // 如果新值value大于旧值x，则说明蛇在向右走，此时发生掉头，应该使蛇继续向左走
                value = this.Y - 10;
            }
            else {
                // 向左走
                value = this.Y + 10;
            }
        }
        // 移动身体
        this.moveBody();
        this.head.style.top = value + 'px';
        // 检查有没有撞到自己
        this.checkHeadBody();
    }
    // 蛇增加身体的方法
    addBody() {
        // 像element中添加一个div
        this.element.insertAdjacentHTML('beforeend', '<div></div>');
    }
    // 添加一个蛇身体移动的方法
    moveBody() {
        /*
            将后边的身体设置为前边身体的位置
                举例子：
                    第4节 = 第3节的位置
                    第3节 = 第2节的位置
                    第2节 = 舌头的位置
        */
        //    便利获取所有的身体
        for (let i = this.bodies.length - 1; i > 0; i--) {
            //获取前边身体的位置
            let X = this.bodies[i - 1].offsetLeft;
            let Y = this.bodies[i - 1].offsetTop;
            // 将值设置到当前身体上
            this.bodies[i].style.left = X + 'px';
            this.bodies[i].style.top = Y + 'px';
        }
    }
    // 检查头和身体有没有相撞
    checkHeadBody() {
        //获取所有的身体，检查其是否和蛇头的坐标发生重叠
        for (let i = 1; i < this.bodies.length; i++) {
            let bd = this.bodies[i];
            if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
                //    进入判断，说明蛇头撞到了身体，游戏结束
                throw new Error("碰到自己了，游戏结束，GameOver！");
            }
        }
    }
}
// 定义一个游戏控制类，控制所有的类
class GameControl {
    constructor(degree) {
        // 创建一个属性来存储蛇的移动方向
        this.direction = 'ArrowRight';
        // 创建一个属性用来记录游戏是否结束
        this.isLive = true;
        this.snake = new Snake();
        this.food = new Food();
        this.scorePanel = new ScorePanel(10, degree);
        this.init();
    }
    // 游戏初始化方法，调用后，游戏即开始
    init() {
        // 绑定键盘按下的事件
        document.addEventListener('keydown', this.keydownHandler.bind(this));
        // 调用run方法，使蛇移动
        this.run();
    }
    keydownHandler(e) {
        this.direction = e.key;
    }
    // 创建一个控制蛇移动的方法
    run() {
        // 获取蛇现在坐标
        let X = this.snake.X;
        let Y = this.snake.Y;
        /*
            上下左右键
            ArrowUp
            ArrowDown
            ArrowLeft
            ArrowRight
        */
        switch (this.direction) {
            case 'ArrowUp':
            case 'Up':
                Y -= 10;
                break;
            case 'ArrowDown':
            case 'Down':
                Y += 10;
                break;
            case 'ArrowLeft':
            case 'Left':
                X -= 10;
                break;
            case 'ArrowRight':
            case 'Right':
                X += 10;
                break;
        }
        // 检查蛇是否吃到了食物
        this.checkEat(X, Y);
        // 修改蛇的X、Y
        try {
            this.snake.X = X;
            this.snake.Y = Y;
        }
        catch (error) {
            alert(error.message);
            location.reload();
            //isLive改成false，游戏结束
            this.isLive = false;
        }
        this.isLive && setTimeout(this.run.bind(this), 300 - (this.scorePanel.level - 1) * 30);
    }
    // 定义一个方法，用来检测蛇是否吃到食物
    checkEat(X, Y) {
        if (X === this.food.x && Y === this.food.y) {
            console.log('吃到食物了');
            // 食物的位置要进行充值
            this.food.change();
            // 分数增加
            this.scorePanel.addScore();
            // 蛇要增加一节
            this.snake.addBody();
        }
    }
}
function startGameFn() {
    let startGame = document.getElementById('startGame');
    console.log(startGame);
    startGame.addEventListener('click', function () {
        this.style.display = 'none';
        let degree = Number(prompt('请输入你想要挑战的等级\n一共10级，难度一次递减'));
        if (degree && degree > 0 && degree <= 10) {
            const g = new GameControl(degree);
        }
        else {
            alert('输入有误！');
            this.style.display = 'block';
        }
    });
}
startGameFn();
